#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <string>
using namespace std;
using namespace cv;
Mat add_jiaoyan(Mat &image, int n);
Mat tongtaiProcess(Mat &image, double Rh, double Rl);
///////////////////////////为图像添加椒月噪声///////////
int main() {
    Mat src = imread("/home/dao/桌面/week04/src/first.png");
    Mat dst;
    cvtColor(src, dst, COLOR_BGR2GRAY);
    Mat dstResult = add_jiaoyan(dst, 10000);
    Mat srcResult = add_jiaoyan(src, 10000);
    Mat dstResultProcess = tongtaiProcess(dst, 1.5, 0.5);
    // medianBlur(dstResult, dstResultProcess02, 3);
    imshow("灰度图像", dst);
    imshow("原图像", src);
    imshow("添加噪声后的灰度图像", dstResult);
    imshow("添加噪声后的彩色图像", srcResult);
    imshow("滤波处理噪声结果", dstResultProcess);
    waitKey(0);
}

Mat add_jiaoyan(Mat &image, int n) {
    Mat image_clone = image.clone();
    for (int k = 0; k < n / 2; k++) {
        int i = rand() % image_clone.rows;
        int j = rand() % image_clone.cols;
        int num = rand() % 2;
        if (num == 0) {
            if (image_clone.type() == CV_8UC3) {
                image_clone.at<Vec3b>(i, j)[0] = 0;
                image_clone.at<Vec3b>(i, j)[1] = 0;
                image_clone.at<Vec3b>(i, j)[2] = 0;
            } else if (image_clone.type() == CV_8UC1) {
                image_clone.at<uchar>(i, j) = 0;
            }
        } else if (num == 1) {
            if (image_clone.type() == CV_8UC3) {
                image_clone.at<Vec3b>(i, j)[0] = 1;
                image_clone.at<Vec3b>(i, j)[1] = 1;
                image_clone.at<Vec3b>(i, j)[2] = 1;
            } else if (image_clone.type() == CV_8UC1) {
                image_clone.at<uchar>(i, j) = 1;
            }
        }
    }
    return image_clone;
}
Mat tongtaiProcess(Mat &image, double Rh, double Rl) {
    Mat newimage = image.clone();
    newimage.convertTo(newimage, CV_64FC1);
    int rows = newimage.rows;
    int cols = newimage.cols;
    int m = rows % 2 == 1 ? rows + 1 : rows;
    int n = cols % 2 == 1 ? cols + 1 : cols;
    copyMakeBorder(newimage, newimage, 0, m - rows, 0, n - cols, BORDER_CONSTANT, Scalar::all(0));
    rows = newimage.rows;
    cols = newimage.cols;
    //对数化
    for (int i = 0; i < rows; i++) {
        double *p1 = newimage.ptr<double>(i);
        double *p2 = newimage.ptr<double>(i);
        for (int j = 0; j < cols; j++) {
            p1[j] = log(p2[j] + 0.0001);
        }
    }
    //傅里叶变换
    Mat newimage_dct = Mat::zeros(newimage.rows, newimage.cols, CV_64FC1);
    dct(newimage, newimage_dct);
    //图向滤波 //H(u,v)1​=(Rh−Rl)[1−exp(−c(D(u,v)/D0​)2n)]+Rl
    Mat temp_image = Mat::zeros(newimage.rows, newimage.cols, CV_64FC1);
    int D0 = (rows / 2) * (rows / 2) + (cols / 2) * (cols / 2);
    int c = 1;
    for (int i = 0; i < rows; i++) {
        double *p0 = temp_image.ptr<double>(i);
        for (int j = 0; j < cols; j++) {
            // int D1 = (i + 1) * (i + 1) + (j + 1) * (j + 1);
            int D1 = i * i + j * j;
            p0[j] = (Rh - Rl) * (1 - exp(-c * (D1 / D0))) + Rl;
        }
    }
    temp_image.ptr<double>(0)[0] = 1.1;
    newimage_dct = newimage_dct.mul(temp_image);
    //逆变换
    idct(newimage_dct, newimage);
    //米运算，逆对书
    for (int i = 0; i < rows; i++) {
        double *p1 = newimage.ptr<double>(i);
        double *p2 = newimage.ptr<double>(i);
        for (int j = 0; j < cols; j++) {
            p1[j] = exp(p2[j]);
        }
    }
    newimage.convertTo(newimage, CV_8UC1);
    return newimage;
}
